//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
/*
 * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of Thomas Roell not be used in
 * advertising or publicity pertaining to distribution of the software without
 * specific, written prior permission.  Thomas Roell makes no representations
 * about the suitability of this software for any purpose.  It is provided
 * "as is" without express or implied warranty.
 *
 * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 * EVENT SHALL THOMAS ROELL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 *
 */

#ifndef _COMPILER_H
#define _COMPILER_H
#include "osenv.h"

#define ldq_u(p)    (*((unsigned long  *)(p)))
#define ldl_u(p)    (*((unsigned int   *)(p)))
#define ldw_u(p)    (*((unsigned short *)(p)))
#define stq_u(v,p)    ((unsigned long  *)(p)) = (v)
#define stl_u(v,p)    ((unsigned int   *)(p)) = (v)
#define stw_u(v,p)    ((unsigned short *)(p)) = (v)
#define mem_barrier()         /* NOP */
#define write_mem_barrier()   /* NOP */


/*
 *-----------------------------------------------------------------------
 * Port manipulation convenience functions
 *-----------------------------------------------------------------------
 */

#if defined(ZEE_USER)
#ifndef _GNUC
__inline UInt8 Inb( IO_PORT This)
{
    __asm {
        mov dx,This;
        in al,dx;
    }
}
__inline void Outb( IO_PORT This, UInt8 Value)
{
    __asm {
        mov dx,This;
        mov al,Value;
        out dx,al;
    }
}

__inline UInt16 inw( IO_PORT This)
{
    __asm {
        mov dx,This;
        in ax,dx;
    }
}
__inline void Outw( IO_PORT This, UInt16 Value)
{
    __asm {
        mov dx,This;
        mov ax,Value;
        out dx,ax;
    }
}

__inline UInt32 inl( IO_PORT This)
{
    __asm {
        mov dx,This;
        in eax,dx;
    }
}

__inline void outl( IO_PORT This, UInt32 Value)
{
    __asm {
        mov dx,This;
        mov eax,Value;
        out dx,eax;
    }
}
#endif
#else
extern PIZFILE IoPort;
INLINE UInt8 Inb( IO_PORT This)
{
    char buffer[5];
    UInt32 readsize;
    UInt32 readdata;

#ifdef __cplusplus
    IoPort->ReadAt(This, (unsigned char *)buffer, 1, &readsize);
#else
    IoPort->v->ReadAt(IoPort, This, buffer, 1, &readsize);
#endif

    readdata = buffer[0];

    return (UInt8)readdata;
}
__inline void Outb( IO_PORT This, UInt8 Value)
{
    char buffer[5];
    UInt32 Writesize;

    buffer[0] = Value;
    buffer[1] = 0;

#ifdef __cplusplus
    IoPort->WriteAt(This, (unsigned char *)buffer, 1, &Writesize);
#else
    IoPort->v->WriteAt(IoPort, This, buffer, 1, &Writesize);
#endif

    return;
}

__inline UInt16 inw( IO_PORT This)
{
    char buffer[5];
    UInt32 readsize;
    UInt32 readdata;

#ifdef __cplusplus
    IoPort->ReadAt(This, (unsigned char *)buffer, 2, &readsize);
#else
    IoPort->v->ReadAt(IoPort, This, buffer, 2, &readsize);
#endif

    readdata = buffer[0];
    readdata += (buffer[1]<<8);

    return (UInt16)readdata;
}
__inline void Outw( IO_PORT This, UInt16 Value)
{
    char buffer[5];
    UInt32 Writesize;

    buffer[0] = (char)Value;
    buffer[1] = Value>>8;
    buffer[2] = 0;

#ifdef __cplusplus
    IoPort->WriteAt(This, (unsigned char *)buffer, 2, &Writesize);
#else
    IoPort->v->WriteAt(IoPort, This, buffer, 2, &Writesize);
#endif

    return;
}

__inline UInt32 inl( IO_PORT This)
{
    char buffer[5];
    UInt32 readsize;
    UInt32 readdata;

#ifdef __cplusplus
    IoPort->ReadAt(This, (unsigned char *)buffer, 4, &readsize);
#else
    IoPort->v->ReadAt(IoPort, This, buffer, 4, &readsize);
#endif

    readdata = buffer[0];
    readdata += buffer[1]<<8;
    readdata += buffer[2]<<16;
    readdata += buffer[3]<<24;

    return (UInt32)readdata;
}

__inline void outl( IO_PORT This, UInt32 Value)
{
    char buffer[5];
    UInt32 Writesize;

    buffer[0] = Value;
    buffer[1] = Value>>8;
    buffer[2] = Value>>16;
    buffer[3] = Value>>24;
    buffer[4] = 0;

#ifdef __cplusplus
    IoPort->WriteAt(This, (unsigned char *)buffer, 4, &Writesize);
#else
    IoPort->v->WriteAt(IoPort, This, buffer, 4, &Writesize);
#endif

    return;
}
#endif


/*
 * rdinx - read the indexed byte port 'port', index 'ind', and return its value
 */
static __inline unsigned char
rdinx(unsigned short int port, unsigned char ind)
{
    if (port == 0x3C0)        /* reset attribute flip-flop */
        (void) Inb(0x3DA);
    Outb(port, ind);
    return(Inb(port+1));
}

/*
 * wrinx - write 'val' to port 'port', index 'ind'
 */
static __inline void
wrinx(unsigned short int port, unsigned char ind, unsigned char val)
{
    Outb(port, ind);
    Outb(port+1, val);
}

/*
 * modinx - in register 'port', index 'ind', set the bits in 'mask' as in 'new';
 *        the other bits are unchanged.
 */
static __inline void
modinx(unsigned short int port, unsigned char ind,
       unsigned char mask, unsigned char thisnew)
{
    unsigned char tmp;

    tmp = (rdinx(port, ind) & ~mask) | (thisnew & mask);
    wrinx(port, ind, tmp);
}

/*
 * tstrg - returns true iff the bits in 'mask' of register 'port' are
 *       readable & writable.
 */

static __inline int
testrg(unsigned short int port, unsigned char mask)
{
    unsigned char old, new1, new2;

    old = Inb(port);
    Outb(port, old & ~mask);
    new1 = Inb(port) & mask;
    Outb(port, old | mask);
    new2 = Inb(port) & mask;
    Outb(port, old);
    return((new1 == 0) && (new2 == mask));
}

/*
 * testinx2 - returns true iff the bits in 'mask' of register 'port', index
 *          'ind' are readable & writable.
 */
static __inline int
testinx2(unsigned short int port, unsigned char ind, unsigned char mask)
{
    unsigned char old, new1, new2;

    old = rdinx(port, ind);
    wrinx(port, ind, old & ~mask);
    new1 = rdinx(port, ind) & mask;
    wrinx(port, ind, old | mask);
    new2 = rdinx(port, ind) & mask;
    wrinx(port, ind, old);
    return((new1 == 0) && (new2 == mask));
}

/*
 * testinx - returns true iff all bits of register 'port', index 'ind' are
 *              readable & writable.
 */
static __inline int
testinx(unsigned short int port, unsigned char ind)
{
    return(testinx2(port, ind, 0xFF));
}

#endif /* _COMPILER_H */
